<script lang="ts">
import {defineComponent} from 'vue'
import {Matrix} from "@/components/comm/matrix";
import {Position, range, spiralIter4d} from "@/components/comm/utils";
import Hammer from 'hammerjs'

export default defineComponent({
  name: "C2048",
  data() {
    return {
      matrix: Matrix.from(4, 4, () => 0),
      message: '',
      hammer: null as HammerManager | null,
    }
  },
  mounted() {
    this.produce();
    if (typeof window !== 'undefined') {
      // 1. 创建 Hammer 实例
      this.hammer = new Hammer(this.$refs.board as HTMLElement);
      // 2. 允许四向识别（默认只有左右）
      this.hammer.get('swipe').set({direction: Hammer.DIRECTION_ALL})
      // 3. 绑定四个事件
      this.hammer.on('swipeleft swiperight swipeup swipedown', this.onSwipe)
    }
    document.addEventListener('keydown', this.onKeyDown);
  },
  beforeUnmount() {          // Vue 3 生命周期
    this.hammer?.off('swipeleft swiperight swipeup swipedown', this.onSwipe);
    document.removeEventListener('keydown', this.onKeyDown);
  },
  methods: {
    range,
    produce(): void {
      const indexes = Array.from(this.matrix.indexes())
          .filter((pos) => this.matrix.get(pos) == 0);
      indexes.sort(() => Math.random() - 0.5)
          .slice(0, 2)
          .forEach((pos) =>
              this.matrix.set(pos, Math.random() < 0.9 ? 2 : 4)
          );
    },
    processLine(indexes: Position[]): void {
      const res: number[] = [];
      let last = 0;
      for (const pos of indexes) {
        const v = this.matrix.get(pos);
        if (v == 0) {
          continue;
        }
        if (last == v) {
          res.push(last + v);
          last = 0;
        } else {
          if (last !== 0) {
            res.push(last);
          }
          last = v;
        }
      }
      if (last !== 0) {
        res.push(last);
      }
      for (const [si, pos] of indexes.entries()) {
        this.matrix.set(pos, res[si] ?? 0);
      }
    },
    checkOver() {
      for (const pos of this.matrix.indexes()) {
        if (this.matrix.get(pos) == 0) {
          return;
        }
        for (const dPos of spiralIter4d(pos, 1, 1)) {
          if (this.matrix.get(dPos, 0) == this.matrix.get(pos)) {
            return;
          }
        }
      }
      this.over();
    },
    move(dir: string) {
      switch (dir) {
        case 'left':
          this.matrix.rowIndexes().map(this.processLine);
          break;
        case 'right':
          this.matrix.rowIndexes().map(a => a.reverse()).map(this.processLine);
          break;
        case 'up':
          this.matrix.colIndexes().map(this.processLine);
          break;
        case 'down':
          this.matrix.colIndexes().map(a => a.reverse()).map(this.processLine);
          break;
      }
      this.produce();
      this.checkOver();
    },
    over() {
      this.message = '游戏结束！';
    },
    restart() {
      this.message = '';
      this.matrix.fill(0);
      this.produce();
    },
    onSwipe(ev: HammerInput) {
      this.move(ev.type.replace('swipe', ''));
    },
    onKeyDown(ev: KeyboardEvent) {
      if (ev.code.startsWith('Arrow')) {
        this.move(ev.code.replace('Arrow', '').toLowerCase());
      }
    },
    cellTheme(n: number) {
      // 1. 预定义 ≤2048 的固定色
      const fixed: Record<number, string> = {
        2: '#eee4da', 4: '#ede0c8', 8: '#f2b179', 16: '#f59563',
        32: '#f67c5f', 64: '#f65e3b', 128: '#edcf72',
        256: '#edcc61', 512: '#edc850', 1024: '#edc53f', 2048: '#edc22e'
      };

      // 2. >2048 用渐变公式
      if (n > 2048) {
        // 阶数越大 hue 越小（偏红），饱和度/亮度保持高位
        const step = Math.log2(n) - 11;          // 2048=2^11
        const hue = Math.max(0, 50 - step * 8); // 从 50° 开始往 0° 偏红
        return {
          background: `hsl(${hue}, 85%, 55%)`,
          color: '#fff'
        };
      }

      // 3. 正常≤2048
      const background = fixed[n] || '#cdc1b4';
      const color = n > 4 ? '#f9f6f2' : '#776e65';
      return {background, color};
    },
  },
})
</script>

<template>
  <div class="main">
    <h1>2048</h1>
    <div class="board" ref="board">
      <template v-for="i of range(4)">
        <div v-for="j of range(4)">
          <div class="cell" :style="cellTheme(matrix.get([i, j]))">
            {{ matrix.get([i, j]) || '' }}
          </div>
        </div>
      </template>
    </div>
    <button class="restart" @click="restart">重新开始</button>
    <div class="message">{{ message }}</div>
  </div>
</template>

<style scoped>
.main {
  text-align: center;
  font-family: Arial, sans-serif;
}

.board {
  display: grid;
  grid-template-columns: repeat(4, min(100px, 20vw, 20vh));
  gap: 5px;
  justify-content: center;
}

.cell {
  width: min(100px, 20vw, 20vh);
  height: min(100px, 20vw, 20vh);
  font-size: 2em;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #333;
}

.message {
  margin-top: 20px;
  font-size: 1.2em;
}

.restart {
  margin-top: 10px;
  padding: 10px 20px;
  font-size: 1em;
  cursor: pointer;
  background-color: blue;
  color: white;
  border: none;
}
</style>